package compiler.lexer;

import compiler.error.ErrorHandler;
import compiler.input.Input;

import java.util.HashMap;
import java.util.Map;


public class MacroHandler {
    /*
     * 宏定义如下：
	 * 宏名称 <空格>  宏内容 [<空格>]
	 */

    private HashMap<String, String> macroMap = new HashMap<>();
    private Input input;

    public MacroHandler(Input input) {
        System.out.println("enter reg macro");

        this.input = input;

        input.readInput();

        while (input.lookAhead() != Input.EOF) {
            //循环编译多行宏定义
            newMacro();
        }
    }

    private void newMacro() {
        /*
         * 将宏定义加入哈希表
		 * 哈希表的key 用的是宏定义的名称，哈希表的内容是宏定义的内容
		 */
        //去掉开头的空格或空行
        while (Input.isSkipChar(input.lookAhead())) {
            input.advance();
        }

        String macroName = fetchContent();

        //忽略宏定义名称后面的空格
        while (Character.isSpaceChar(input.lookAhead())) {
            input.advance();
        }

        //获取宏定义的内容
        String macroContent = fetchContent();


        //越过 ' ' '\n'
        while (Input.isSkipChar(input.lookAhead())) {
            input.advance();
        }

        //将宏定义加入哈希表
        macroMap.put(macroName, macroContent);
    }

    private String fetchContent() {
        StringBuilder builder = new StringBuilder();
        int character = input.lookAhead();
        while (!Input.isSkipChar(character)) {
            builder.append((char) character);
            input.advance();
            character = input.lookAhead();
        }
        return builder.toString();
    }

    public String expandMacro(String macroName) {
        if (macroMap.containsKey(macroName)) {
            return "(" + macroMap.get(macroName) + ")";
        }

        ErrorHandler.parseErr(ErrorHandler.Error.E_NOMAC);
        return "ERROR";
    }

    public void printMacs() {
        if (macroMap.isEmpty()) {
            System.out.println("There are no macros");
            return;
        }
        for (Map.Entry<String, String> entry : macroMap.entrySet()) {
            System.out.println("Macro name: "
                    + entry.getKey()
                    + " Macro content: "
                    + entry.getValue());
        }
    }
}
